part of _;

extension on ChatPage {
  void controller_broadcasts() {
    yBroadcast_register(IFinal.Broadcasts.onRecMessage, (map) async {
      controller_clearUnReadCount();
      controller_sendMessageReceipt();
      final messages = map!["messages"] as List<YIMMessage>;
      MessageUtils.onRecMessage(page: this, messages: messages);
      final newMessages = messages.map((message) => MessageModel.fromYIMMessage(message, message.from == globalUserModel!.yim_user)).toList();
      final isBottom = scrollController.offset <= 0; //判断原本是否在底部
      if (isBottom) {
        controller_addMessages(messages: newMessages);
        controller_scrollToBottom();
      } else {
        tempMessages.addAll(newMessages);
      }
    });
    yBroadcast_register(IFinal.Broadcasts.onRecRevoke, (map) async {
      final revokeMessage = map!["message"] as YIMRevokeMessage;
      messages.forEach((message) {
        if (revokeMessage.conversationID == this.serviceID && revokeMessage.messageID == message.id) {
          message.isRevoke = true;
          setState(() {});
          return;
        }
      });
    });
    yBroadcast_register(IFinal.Broadcasts.onRecReceipt, (map) async {
      final conversationID = map!["conversationID"] as String;
      if (conversationID != this.serviceID) return;
      messages.forEach((message) {
        message.messageState = YIMEnum_MessageState.Success_Read;
      });
      setState(() {});
    });
    yBroadcast_register(IFinal.Broadcasts.onSendFinish, (map) {
      final yimMessage = map!["yimMessage"] as YIMMessage;
      messages.firstWhere((element) => element.id == yimMessage.id).messageState = yimMessage.messageState;
      setState(() {});
    });
  }

  void controller_clearUnReadCount() {
    YIM.conversationManager.clearUnreadCount(conversationType: YIMEnum_ConversationType.P2P, conversationID: serviceID);
  }

  void controller_sendMessageReceipt() {
    YIM.messageManager.sendMessageReceipt(conversationType: YIMEnum_ConversationType.P2P, conversationID: serviceID);
  }

  Future<void> controller_loadMessages() async {
    YIM.messageManager.queryLocalMessages(
      conversationType: YIMEnum_ConversationType.P2P,
      conversationID: serviceID,
      time: messages.isEmpty ? null : DateTime.fromMillisecondsSinceEpoch(messages.last.date),
      limit: 20,
      callback: (messages) async {
        yRun(() => setState(() => isPullRefreshing = false), delay: 500);
        if (messages == null || messages.isEmpty) return;
        controller_addMessages(messages: messages.map((message) => MessageModel.fromYIMMessage(message, message.from == globalUserModel!.yim_user)).toList().reversed, isTop: true);
      },
    );
  }

  void controller_addListeners() {
    focusNode.addListener(() {
      if (focusNode.hasFocus) {
        chatInputType = ChatInputType.Inputing;
      } else {
        chatInputType = ChatInputType.Idle;
      }
      controller_scrollToBottom(checkIsBottom: true);
      setState(() {});
    });
    scrollController.addListener(() {
      //分页
      if (!isPullRefreshing) {
        if (scrollController.offset >= scrollController.position.maxScrollExtent) {
          setState(() => isPullRefreshing = true);
          controller_loadMessages();
        }
      }
      //加载未滚动到底部时收到的消息
      if (tempMessages.isNotEmpty) {
        if (scrollController.offset <= 0) {
          controller_addMessages(messages: tempMessages);
          tempMessages.clear();
        }
      }
    });
  }

  void controller_scrollToBottom({bool checkIsBottom = false}) {
    yRun(() {
      if (checkIsBottom) {
        if (scrollController.offset > 0) return;
      }
      scrollController.jumpTo(0);
    });
  }

  void controller_sendMessage(Enum_MessageType messageType, String content, {Function(YIMMessage yimMessage)? onSendStart}) async {
    YIM.messageManager.sendTextMessage(
      conversationType: YIMEnum_ConversationType.P2P,
      conversationID: serviceID,
      content: json.encode(
        OriginMessageModel()
          ..avatar_from = globalUserModel!.avatar
          ..avatar_to = serviceAvatar
          ..name_from = globalUserModel!.name
          ..name_to = serviceName
          ..type = messageType
          ..content = content,
      ),
      callback_start: (yimMessage) {
        onSendStart?.call(yimMessage);
      },
      callback_finish: (isSuccess, yimMessage, code, msg) {
        yBroadcast_send(IFinal.Broadcasts.onSendFinish, params: {
          "yimMessage": yimMessage,
        });
      },
    );
  }

  void controller_addMessages({required Iterable<MessageModel> messages, bool isTop = false}) {
    if (isTop) {
      this.messages.addAll(messages);
    } else {
      this.messages.insertAll(0, messages);
    }
    setState(() {});
  }

  void controller_more() {
    yShowActionSheet("请选择", ["清空记录"], (index, action) async {
      switch (action) {
        case "清空记录":
          await YIM.messageManager.clearLocalMessage(YIMEnum_ConversationType.P2P, serviceID);
          messages.clear();
          setState(() {});
          yToast("清空成功");
          break;
      }
    });
  }

  void controller_functionClick(Map<String, dynamic> item) async {
    Future<void> upload(List<AssetEntity?>? assets) async {
      if (assets == null || assets.isEmpty || assets.any((element) => element == null)) return;
      switch (assets.first!.type) {
        case AssetType.image:
          List<String> filePaths = [];
          for (final asset in assets) {
            filePaths.add((await asset!.file)!.path);
          }
          addUploadMessages(
            filePaths,
            Enum_MessageType.Image,
            onMessagePrepare: (messageModel) async {
              setState(() {});
              controller_scrollToBottom();
              messageModel.content = await CompressUtils.compressImage(messageModel.content);
              return messageModel;
            },
          );
          break;
        case AssetType.video:
          addUploadMessages(
            [(await assets.first!.file)!.path],
            Enum_MessageType.Video,
            onMessagePrepare: (messageModel) async {
              messageModel.videoThumbnailPath = (await VideoCompress.getFileThumbnail(messageModel.content)).path;
              setState(() {});
              controller_scrollToBottom();
              messageModel.content = await CompressUtils.compressVideo(messageModel.content);
              return messageModel;
            },
          );
          break;
        default:
          break;
      }
    }

    switch (item["title"]) {
      case "相册":
        await upload(await AssetUtils.selectAssets(
          maxAssets: 9,
          specialPickerType: SpecialPickerType.wechatMoment,
        ));
        break;
      case "拍摄":
        await upload([await AssetUtils.pickFromCamera()]);
        break;
      default:
        yToast("尚未支持的功能");
        break;
    }
  }

  void controller_faceClick(int index) {
    chatInputType = ChatInputType.Face;
    setState(() {});
    final face = "[emoticon_${index + 1}]";
    final cursorIndex = textEditingController.selection.baseOffset;
    if (cursorIndex < 0) {
      textEditingController.text = face;
      textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: face.length));
      return;
    }
    if (cursorIndex == 0) {
      textEditingController.text = "$face${textEditingController.text.substring(cursorIndex, textEditingController.text.length)}";
      textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: cursorIndex + face.length));
      return;
    }
    textEditingController.text = "${textEditingController.text.substring(0, cursorIndex)}$face${textEditingController.text.substring(cursorIndex, textEditingController.text.length)}";
    textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: cursorIndex + face.length));
  }

  void controller_faceDeleteClick() {
    final cursorIndex = textEditingController.selection.baseOffset;
    if (cursorIndex <= 0) return;
    if (cursorIndex <= 1) {
      textEditingController.text = "${textEditingController.text.substring(cursorIndex, textEditingController.text.length)}";
      textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: 0));
      return;
    }
    final curChar = textEditingController.text.characters.getRange(cursorIndex - 1, cursorIndex).string;
    if (curChar != "]" || !textEditingController.text.substring(0, cursorIndex - 1).contains(EmojiText.prefix)) {
      textEditingController.text = "${textEditingController.text.substring(0, cursorIndex - 1)}${textEditingController.text.substring(cursorIndex, textEditingController.text.length)}";
      textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: cursorIndex - 1));
      return;
    }
    final emojiStartIndex = textEditingController.text.substring(0, cursorIndex - 1).lastIndexOf(EmojiText.prefix);
    textEditingController.text = "${textEditingController.text.substring(0, emojiStartIndex)}${textEditingController.text.substring(cursorIndex, textEditingController.text.length)}";
    textEditingController.selection = TextSelection.fromPosition(TextPosition(offset: emojiStartIndex));
    setState(() {});
  }
}
